﻿using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using System.Runtime.Serialization;
using ArtMath.Component;
using ArtMath.Flag;
using System.Linq;
using ArtMath.Setting;
using ArtMath.CommonType;

namespace ArtMath.Control
{
    /// <summary>
    /// 表示元件和画板的层叠列表项
    /// </summary>
    [Serializable]
    public class LayerItem : IComparable<LayerItem>, IObjectState//, ISerializable
    {
        bool visible = true, selected, locked;
        //ObjectState objState = ObjectState.Normal;
        string name;
        public bool Searched;
        int indentLevel = 0;
        FolderLayerItem host;
        public event Action HostChanged;
        [NonSerialized]
        ItemPanel itemContainer;
        [Browsable(false)]
        public ItemPanel ItemContainer
        {
            get { return itemContainer; }
            private set { itemContainer = value; }
        }
        [NonSerialized]
        PictureBox pbView, pbLock;
        [NonSerialized]
        TextBox tbEdit;
        //[Browsable(false)]
        public Base LinkedObj { get; set; }
        [NonSerialized]
        LayerControl layer;
        public LayerControl Layer
        {
            get { return layer; }
            set
            {
                if (layer != null)
                {
                    Selected_ = false;
                    layer.Items.Remove(this);
                    layer.SelectedOnceCount--;
                    layer.Controls.Remove(ItemContainer);
                }
                layer = value;
                if (layer != null)
                {
                    layer.Controls.Add(ItemContainer);
                    layer.Items.Add(this);
                    layer.SelectedOnceCount++;
                }
            }
        }
        public LayerItem(string name, Base linkedObj)
        {
            LinkedObj = linkedObj;
            buildItemControls();
            Name = name;
        }
        public int LayerItemHeight
        {
            get { return ItemContainer.Height; }
            set
            {
                if (value < 0) return;
                ItemContainer.Height = value;
                if (pbView != null)
                {
                    pbView.Size = new Size(ItemContainer.ClientSize.Height - 2, ItemContainer.ClientSize.Height - 2);
                }
                ItemContainer.Refresh();
            }
        }
        public class ItemPanel : Panel
        {
            public ItemPanel()
            {
                DoubleBuffered = true;
                BackColor = Color.FromKnownColor(KnownColor.Window);
                Dock = DockStyle.Top;
                Height = Settings.Instance.LayerItemHeight;
            }
        }
        void buildItemControls()
        {
            ItemContainer = new ItemPanel();
            ItemContainer.Paint += Panel_Paint;
            ItemContainer.Click += (object sender, EventArgs e) =>
            {
                Item_Click();
            };
            ItemContainer.MouseEnter += (object sender, EventArgs e) =>
            {
                if (!Selected) ItemContainer.BackColor = Color.FromArgb(229, 243, 255);
            };
            ItemContainer.MouseDown += (object sender, MouseEventArgs e) =>
            {
                if (!Selected) ItemContainer.BackColor = Color.FromArgb(204, 232, 255);
                switch (e.Button)
                {
                    case MouseButtons.Right:
                        Item_Click();
                        if (Layer.SelectedItems.Count == 1 && Layer.SelectedItems[0].LinkPad)
                        {

                        }
                        else
                        {
                            ContextMenuStrip cms = Layer.Pad.CreateMenuForObject(Layer.SelectedItems.Select((LayerItem item) => { return item.LinkedObj; }));
                            ItemContainer.ContextMenuStrip = cms;
                        }
                        break;
                }
            };
            ItemContainer.MouseLeave += (object sender, EventArgs e) =>
            {
                if (!Selected)
                {
                    if (ItemContainer.ContextMenuStrip != null && ItemContainer.ContextMenuStrip.Visible)
                    {

                    }
                    else
                    {
                        ItemContainer.BackColor = Searched ? Color.Orange : Color.FromKnownColor(KnownColor.Window);
                    }
                }
            };
            ItemContainer.DoubleClick += Panel_DblClick;
            pbView = new PictureBox()
            {
                Image = Resource.Properties.Resources.visible,
                SizeMode = PictureBoxSizeMode.CenterImage,
                Size = new Size(ItemContainer.ClientSize.Height - 2, ItemContainer.ClientSize.Height - 2),
                Location = new Point(1, 1),
                Cursor = Cursors.Hand,
            };
            pbView.MouseDown += View_MouseDown;
            pbView.MouseEnter += (object sender, EventArgs e) =>
            {
                if (!Selected) ItemContainer.BackColor = Color.FromArgb(229, 243, 255);
            };
            pbView.MouseLeave += (object sender, EventArgs e) =>
            {
                if (!Selected) ItemContainer.BackColor = Color.FromKnownColor(KnownColor.Window);
            };
            ItemContainer.Controls.Add(pbView);
            pbLock = new PictureBox()
            {
                Image = Resource.Properties.Resources._lock,
                SizeMode = PictureBoxSizeMode.CenterImage,
                Size = new Size(ItemContainer.ClientSize.Height - 2, ItemContainer.ClientSize.Height - 2),
                Location = new Point(ItemContainer.ClientSize.Width - ItemContainer.ClientSize.Height + 1, 1),
                Anchor = AnchorStyles.Right | AnchorStyles.Top,
                Cursor = Cursors.Hand,
            };
            pbLock.Hide();
            //pbLock.MouseDown += new MouseEventHandler(pb_MouseDown);
            //pbLock.MouseEnter += new EventHandler(delegate (object sender, EventArgs e) { if (!Selected) panel.BackColor = Color.LightSkyBlue; });
            //pbLock.MouseLeave += new EventHandler(delegate (object sender, EventArgs e) { if (!Selected) panel.BackColor = Color.White; });
            ItemContainer.Controls.Add(pbLock);
            tbEdit = new TextBox()
            {
                Tag = name,
                Visible = false,
            };
            tbEdit.Location = new Point(pbView.Right + 7, (ItemContainer.Height - tbEdit.Height) / 2 - 1);
            tbEdit.Invalidated += (object sender, InvalidateEventArgs e) =>
            {
                if (tbEdit.Text != tbEdit.Tag as string)
                {
                    if (LinkedObj == null)
                    {
                        if (LinkPad)
                        {
                            Layer.Pad.Name = tbEdit.Text;
                        }
                        else
                        {
                            Name = tbEdit.Text;
                        }
                    }
                    else
                    {
                        LinkedObj.Name = tbEdit.Text;
                    }
                }
                tbEdit.Hide();
            };
            tbEdit.KeyDown += (object sender, KeyEventArgs e) =>
            {
                if (e.KeyCode == Keys.Enter)
                {
                    tbEdit.Invalidate();
                }
            };
            ItemContainer.Controls.Add(tbEdit);
        }
        [OnDeserialized]
        void onDeserialized(StreamingContext context)
        {
            buildItemControls();
        }

        //LayerItem(SerializationInfo info, StreamingContext context)
        //{
        //    Layer = (info.GetValue("Pad", typeof(SketchPad)) as SketchPad).Layer;
        //    buildItemControls();
        //}
        [Browsable(false)]
        public virtual bool LinkPad
        {
            get { return LinkedObj == null; }
        }
        public void Panel_DblClick(object sender, EventArgs e)
        {
            tbEdit.Text = name;
            tbEdit.Width = ItemContainer.Width - tbEdit.Left - pbLock.Width - 10;
            tbEdit.Show();
            tbEdit.Focus();
            tbEdit.SelectAll();
        }
        public virtual void View_MouseDown(object sender, MouseEventArgs e)
        {
            if (LinkedObj == null)
            {
                LinkedObjectVisible = !LinkedObjectVisible;
                if (LinkPad)
                {
                    Layer.Pad.Canvas.Visible = LinkedObjectVisible;
                }
            }
            else
            {
                LinkedObj.Visible = !LinkedObj.Visible;
            }
            if (!Selected) ItemContainer.BackColor = Color.FromArgb(204, 232, 255);
        }
        public void Item_Click(bool enableFuncKey = true)
        {
            if (Flags.Shift && enableFuncKey)
            {
                int currentIndex = Index;
                if (Layer.SelectedItems.Count == 0)
                {
                    for (int i = currentIndex - Layer.SelectedOnceCount + 1; i <= currentIndex; i++)
                    {
                        if (i >= 0) Layer.Items[i].Selected_ = true;
                    }
                }
                else
                {
                    int firstIndex = Layer.SelectedItems[0].Index, tmp;
                    if (currentIndex > firstIndex)
                    {
                        foreach (LayerItem item in Layer.Items)
                        {
                            if ((tmp = item.Index) >= firstIndex && tmp <= currentIndex)
                            {
                                if (!item.Selected_) item.Selected_ = true;
                            }
                            else
                            {
                                if (item.Selected_) item.Selected_ = false;
                            }
                        }
                    }
                    else
                    {
                        for (int i = Layer.Items.Count - 1; i >= 0; i--)
                        {
                            if ((tmp = Layer.Items[i].Index) >= currentIndex && tmp <= firstIndex)
                            {
                                if (!Layer.Items[i].Selected_) Layer.Items[i].Selected_ = true;
                            }
                            else
                            {
                                if (Layer.Items[i].Selected_) Layer.Items[i].Selected_ = false;
                            }
                        }
                    }
                    Layer.SelectCount(Layer.SelectedOnceCount);
                }
            }
            else if (Flags.Ctrl && enableFuncKey)
            {
                Selected_ = !Selected_;
                Layer.SelectCount(Layer.SelectedOnceCount);
            }
            else
            {
                Layer.Pad.SelectNothing();
                Selected_ = true;
            }
        }
        public void Remove()
        {
            Layer?.Remove(this);
        }
        //public ObjectState ObjectState
        //{
        //    get { return objState; }
        //    set
        //    {
        //        objState = value;
        //        Selected_ = ItemContainer.Visible = objState == ObjectState.Normal;
        //    }
        //}
        public int IndentLevel
        {
            get { return indentLevel; }
            set
            {
                indentLevel = value;
                ItemContainer.Invalidate();
            }
        }
        public FolderLayerItem Host
        {
            get { return host; }
            set
            {
                host = value;
                if (host == null)
                {
                    IndentLevel--;
                }
                else
                {
                    IndentLevel++;
                }
                HostChanged?.Invoke();
            }
        }
        [Browsable(false)]
        public string Name
        {
            get { return name; }
            set
            {
                name = value;
                tbEdit.Tag = name;
                ItemContainer.Invalidate();
            }
        }
        [Browsable(false)]
        public bool Selected
        {
            get { return selected; }
            set
            {
                if (selected == value) return;
                selected = value;
                if (selected)
                {
                    ItemContainer.BackColor = Color.FromArgb(204, 232, 255);
                    Layer.SelectedItems.Add(this);
                    Layer.SelectedItems.Sort();//使被选中的元素相对原序列保持先后顺序不变
                }
                else
                {
                    ItemContainer.BackColor = Color.FromKnownColor(KnownColor.Window);
                    Layer.SelectedItems.Remove(this);
                }
                ItemContainer.Invalidate();
                Layer.RefreshStatus();
            }
        }
        [Browsable(false)]
        public bool Selected_
        {
            get { return Selected; }
            set
            {
                Selected = value;
                if (LinkedObj == null)
                {
                    //layer.pad.Selected = Selected;
                }
                else
                {
                    LinkedObj.Selected_ = Selected;
                    //StyleState ss = StyleState.Normal;
                    //if (Selected)
                    //{
                    //    foreach (Base item in Layer.Pad.SelectedObjects)
                    //    {
                    //        if (item.StyleState_ == StyleState.Hover)
                    //        {
                    //            //ss = StyleState.Hover;
                    //            break;
                    //        }
                    //    }
                    //}
                    //LinkedObj.StyleState_ = ss;
                }
                Layer.Pad.Canvas.Invalidate();
            }
        }
        public int Index
        {
            get { return Layer == null ? -1 : Layer.Items.IndexOf(this); }
            set
            {
                if (value >= 0)
                {
                    int currentIndex = Index;
                    if (value == currentIndex || value > Layer.Items.Count) return;
                    if (value > currentIndex)
                    {
                        value--;
                    }
                    Layer.Items.RemoveAt(currentIndex);
                    Layer.Items.Insert(value, this);
                    Layer.Controls.SetChildIndex(ItemContainer, value);
                    Layer.RefreshStatus();
                    Layer.Pad.Canvas.Invalidate();
                }
            }
        }

        [Browsable(false)]
        public bool LinkedObjectVisible
        {
            get { return visible; }
            set
            {
                visible = value;
                pbView.Image = visible ? Resource.Properties.Resources.visible : Resource.Properties.Resources.invisible;
            }
        }
        public bool Locked
        {
            get { return locked; }
            set
            {
                locked = value;
                ItemContainer.Invalidate();
            }
        }

        public ObjectState ObjectState
        {
            get
            {
                if (LinkPad)
                {
                    return Layer.Pad.ObjectState;
                }
                if (LinkedObj != null)
                {
                    return LinkedObj.ObjectState;
                }
                return ObjectState.Normal;
            }
        }

        public void Swap(int index)
        {
            int currentIndex = Index;
            if (currentIndex == index) return;
            Layer.Items[currentIndex] = Layer.Items[index];
            Layer.Items[index] = this;
            Layer.Controls.SetChildIndex(ItemContainer, Index);
            Layer.RefreshStatus();
            Layer.Pad.Canvas.Invalidate();
        }
        void Panel_Paint(object sender, PaintEventArgs e)
        {
            Graphics gra = e.Graphics;
            Font ft = new Font("Microsoft YaHei", 9);
            Size size = TextRenderer.MeasureText(name, ft);
            gra.DrawString(name, ft, Brushes.Black, 
                pbView.Right + 6 + IndentLevel * 4, (ItemContainer.ClientSize.Height - size.Height) >> 1);
            int top = (ItemContainer.ClientSize.Height - 16) >> 1;
            if (Locked)
            {
                gra.DrawImage(Resource.Properties.Resources._lock, ItemContainer.ClientSize.Width - top - 16, top);
            }
            if (Selected)
            {
                gra.DrawRectangle(new Pen(Color.FromArgb(153, 209, 255), 1), 0, 0, ItemContainer.ClientSize.Width - 1, ItemContainer.ClientSize.Height - 1);
            }
        }
        public int CompareTo(LayerItem other)
        {
            return Index - other.Index;
        }
    }
}
